#!/usr/bin/evn python
# -*- coding: utf-8 -*-

from typing import Union, Optional

import pandas as pd
from fastapi import FastAPI, APIRouter, Cookie
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import Response, FileResponse

from afast_core.core_plugins.aiojobs import AiojobsPluginClient
from afast_core.core_plugins.cache_house import CacheHousePluginClient
from afast_core.core_plugins.pyee_event import EventEmitterPluginClient
from afast_core.core_plugins.redis.syncredis import SyncRedisPluginClient

from afast_core.core_plugins.globalrequest import GlobalRequestPluginClient
from afast_core.core_plugins.loguru.client import LoguruPluginClient
from afast_core.core_plugins.swaggerui import SwaggeruiPluginClient
from afast_core.core_plugins.loguru import logger
from afast_core.core_app import IApplicationBuilder
from infirmary_admin_src.infirmary_smart_admin.infirmary_dependencies.inject_login import smart_admin_check_login
from infirmary_admin_src.infirmary_smart_admin.infirmary_settings.development import DevSettings
from infirmary_admin_src.infirmary_smart_admin.infirmary_settings.production import ProSettings
from infirmary_admin_src.infirmary_smart_admin.infirmary_settings.setting import Environment


# from infirmary_admin_src.infirmary_system.infirmary_settings.development import DevSettings
# from infirmary_admin_src.infirmary_system.infirmary_settings.production import ProSettings
# from infirmary_admin_src.infirmary_system.infirmary_settings.setting import Environment


class FastApplicationBuilder(IApplicationBuilder):

    def __init__(self, *, settings: Union[DevSettings, ProSettings]):
        ''' 创建APP实例对象 '''
        if settings is None:
            # 检测是否存在配置实例对象
            raise RuntimeError('Must provide a valid Settings object')
        self.settings = settings

    @classmethod
    def with_environment_settings(cls) -> 'FastApplicationBuilder':
        ''' 根据当前环境变量选择指定的环境配置实例 '''
        return cls(settings=Environment.select())

    def _instance_app(self) -> FastAPI:
        # 创建实例对象
        return FastAPI(
            title=self.settings.project_name,
            version=self.settings.project_version,
            debug=self.settings.debug,
            # depends=[Depends(Logging)],
        )

    def _register_loguru_log_client(self, app: FastAPI) -> None:
        # 放在在最后处理因为是日志作用，所以一般使用的时候最后再执行注册
        pass
        # 日志插件初始化
        LoguruPluginClient(app=app,
                           settings=LoguruPluginClient.LoguruConfig(PROJECT_SLUG=self.settings.LOG_PROJECT_SLUG,
                                                                    FLITER_REQUEST_URL=self.settings.FLITER_REQUEST_URL,
                                                                    LOG_FILE_PATH=self.settings.LOG_FILE_PATH,
                                                                    MODEL=self.settings.LOG_MODEL)
                           )
        logger.info("LoguruPluginClient插件安装成功")

    def _register_global_request(self, app: FastAPI) -> None:
        # 注册应用全局请求的request
        pass
        GlobalRequestPluginClient(app=app)
        logger.info("GlobalRequestPluginClient插件安装成功")

    def _register_plugins(self, app: FastAPI) -> None:
        # 应用注册注册插件
        pass
        # 离线本地文档浏览
        SwaggeruiPluginClient(app=app, proxy=self.settings.swaggerui_proxy)
        SyncRedisPluginClient(app=app, settings=SyncRedisPluginClient.RedisSettings(
            host='127.0.0.1', port=6379, password=''
        ))
        # # # 缓存插件
        CacheHousePluginClient(app=app, settings=CacheHousePluginClient.CacheSettings(
            host='127.0.0.1', port=6379, password=''
        ))
        # # 异步缓存插件
        # AsyncCashewsPluginClient(app=app, settings=AsyncCashewsPluginClient.CacheSettings(
        #     url='redis://root:123456@127.0.0.1:6379/?db=1&socket_connect_timeout=0.5&safe=0'
        # ))
        # 另一个后台任务的插件
        # AiojobsPluginClient(app=app)
        # 类似信号事件分发插件
        # EventEmitterPluginClient(app=app, settings=EventEmitterPluginClient.EventsSettings(
        #     events_name='events'
        # ))

        # 性能检测数据，打印出相关调用链路的耗时处理
        # ProfilePluginClient(core_app=core_app, configs=ProfilePluginClient.ProfileConfig())
        # # 定时任务===需注意避免本地多worker情况启动多个可以加文件锁或其他锁
        # schedule = RocketrySchedulerPluginClient(core_app=core_app, configs=RocketrySchedulerPluginClient.SchedulerConfig())
        # @schedule.infirmary_tasks('every 5 seconds')
        # async def do_things():
        #     print("定时任务！")
        #
        # @schedule.infirmary_tasks(every('10 seconds', based="finish"))
        # async def do_permanently():
        #     "This runs for really long time"
        #     print(600000)
        #     await asyncio.sleep(600000)
        #
        # @schedule.infirmary_tasks(every('2 seconds', based="finish"))
        # async def do_short():
        #     "This runs for short time"
        #     print(11111)
        #     await asyncio.sleep(1)

    def _register_exception_handlers(self, app: FastAPI) -> None:
        # 应用注册自定义的错误处理机制
        pass
        # 注册某个插件下特定的异常抛出处理
        # from infirmary_admin_src.infirmary_system.infirmary_common.infirmary_errors import setup_snowy_ext_exception
        from infirmary_admin_src.infirmary_common.infirmary_errors.globalexption import setup_snowy_ext_exception
        setup_snowy_ext_exception(app=app)

    def _register_routes(self, app: FastAPI) -> None:
        pass

        logger.info("路由开始注册")
        snowy_app_router = APIRouter(tags=[''], prefix='/adn/api/v1')
        # from infirmary_admin_src.infirmary_business.snowy_modules.core_auth.setup import router_module as core_auth
        # from infirmary_admin_src.infirmary_business.snowy_modules.dev.setup import router_module as dev
        # from src.modules.snowy.modules.sys import router_module as sys
        # from src.modules.snowy.modules.dev import router_module as dev
        # from infirmary_admin_src.infirmary_system.snowy_modules.core_auth.setup import GroupAPIRouterBuilder as core_auth
        # snowy_app_router.include_router(core_auth.instance())

        # from infirmary_admin_src.infirmary_system.snowy_modules.authV1.setup import AGroupAPIRouterBuilder
        # snowy_app_router.include_router(AGroupAPIRouterBuilder.instance())

        # from infirmary_admin_src.infirmary_system.snowy_modules.authV1.setup import GroupAPIRouterBuilder as auth2
        # snowy_app_router.include_router(auth2.instance())

        # 系统模块

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.system.login.setup import \
            AGroupAPIRouterBuilder as SystemMageageLoginBuilder
        snowy_app_router.include_router(SystemMageageLoginBuilder.instance())

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.system.menu.setup import \
            AGroupAPIRouterBuilder as SystemMenuBuilder
        snowy_app_router.include_router(SystemMenuBuilder.instance())

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.system.employee.setup import \
            AGroupAPIRouterBuilder as SystemEmployeeBuilder
        snowy_app_router.include_router(SystemEmployeeBuilder.instance())

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.system.department.setup import \
            AGroupAPIRouterBuilder as SystemDepartmentBuilder
        snowy_app_router.include_router(SystemDepartmentBuilder.instance())

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.system.role.setup import \
            AGroupAPIRouterBuilder as SystemRoleBuilder
        snowy_app_router.include_router(SystemRoleBuilder.instance())

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.system.datascope.setup import \
            AGroupAPIRouterBuilder as SystemDatascopeBuilder
        snowy_app_router.include_router(SystemDatascopeBuilder.instance())

        # ====其他模块

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.changeLog.setup import \
            AGroupAPIRouterBuilder as ChangeLogBuilder
        snowy_app_router.include_router(ChangeLogBuilder.instance())

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.oa.setup import \
            AGroupAPIRouterBuilder as OABuilder
        snowy_app_router.include_router(OABuilder.instance())

        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.support.setup import \
            AGroupAPIRouterBuilder as SupportBuilder
        snowy_app_router.include_router(SupportBuilder.instance())
        # 医馆管理模块
        from infirmary_admin_src.infirmary_smart_admin.infirmary_biz.infirmary.businesses.setup import \
            AGroupAPIRouterBuilder as InfirmaryBusinessesBuilder
        snowy_app_router.include_router(InfirmaryBusinessesBuilder.instance())

        # from infirmary_admin_src.infirmary_system.infirmary_biz.businesses.setup import AGroupAPIRouterBuilder as BusinessesBuilder
        # snowy_app_router.include_router(BusinessesBuilder.instance())
        # from infirmary_admin_src.infirmary_system.infirmary_biz.doctor.setup import AGroupAPIRouterBuilder as DoctorBuilder
        # snowy_app_router.include_router(DoctorBuilder.instance())
        # from infirmary_admin_src.infirmary_system.infirmary_biz.rules.setup import \
        #     AGroupAPIRouterBuilder as RulesBuilder
        # snowy_app_router.include_router(RulesBuilder.instance())
        # from infirmary_admin_src.infirmary_system.infirmary_biz.scheduling_order.setup import \
        #     AGroupAPIRouterBuilder as SchedulingOrderBuilder
        # snowy_app_router.include_router(SchedulingOrderBuilder.instance())

        # snowy_app.include_router(dev)
        logger.info("路由模块插件导入插件安装成功")
        # 加入模块路由组
        from fastapi import Depends
        app.include_router(snowy_app_router, dependencies=[Depends(smart_admin_check_login)])

    def _register_middlewares(self, app: FastAPI) -> None:
        pass
        app.add_middleware(
            CORSMiddleware,
            allow_origins=["*"],
            allow_credentials=True,
            allow_methods=["*"],
            allow_headers=["*"],
        )
        # 测试验证可以读取响应报文和读取请求报文信息的中间件
        from afast_core.core_middleware.request_response import RequestResponseMiddleware
        app.add_middleware(RequestResponseMiddleware)


# ############################################################################
# ############################# 启动说明 #############################
# ############################################################################
# 如果下面的代码放在main中的话，
# core_app = FastApplicationBuilder \
#     .with_environment_settings() \
#     .build()
# 也会类似下面的代码执行两次！
# if __name__ == "__main__":
#     直接在这里跑的会会运行两次，需要注意。所以建议单独放到main中运行，否则一些注册会执行多次
#     import uvicorn
#     import os
#     # 使用os.path.basename函数获取了当前文件的名称，并将.py文件扩展名替换为空字符串
#     app_modeel_name = os.path.basename(__file__).replace(".py", "")
#     # 使用uvicorn.run函数运行了一个应用程序。它指定了应用程序的主机和端口，并且设置了reload参数为True。
#     uvicorn.run(f"{app_modeel_name}:core_app", host='127.0.0.1',port=31100,reload=True)
# ############################################################################
# ############################# 启动说明 #############################
# ############################################################################
app = FastApplicationBuilder \
    .with_environment_settings() \
    .build()
